package com.partners.service.Impl;

import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPaySendRedpackRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPaySendRedpackResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.google.common.collect.Lists;
import com.partners.configure.wechatmp.WxMpProperties;
import com.partners.constant.ErrorMessageEnum;
import com.partners.dao.basic.GroupOrderDao;
import com.partners.dao.basic.UserDao;
import com.partners.dao.bo.GroupOrderDO;
import com.partners.dao.bo.UserDO;
import com.partners.dao.dto.OrderInputDTO;
import com.partners.dao.dto.PayOrderOutputDTO;
import com.partners.model.BusinessException;
import com.partners.service.PayService;
import com.partners.utils.CodeUtils;
import com.partners.utils.TimestampUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.core.annotation.OrderUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liangyongle
 * @date 2019-01-12
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {

    @Resource
    private WxPayService wxPayService;


    @Resource
    private WxMpProperties wxMpProperties;

    @Resource
    private GroupOrderDao groupOrderDao;

    @Resource
    private UserDao userDao;


    /**
     * 统一下单
     * @param  order  OrderInputDTO
     * @return  GroupOrderDO
     * */
    @Override
    @Transactional
    public GroupOrderDO createGroupOrder(OrderInputDTO order) {
        //创建新的订单号
        Byte status = 0;
        String orderNo = CodeUtils.createGroupOrderNum();
        GroupOrderDO groupOrder = new GroupOrderDO();
        groupOrder.setOrderNo(orderNo);
        groupOrder.setBuyId(order.getBuyId());
        groupOrder.setUid(order.getUid());
        groupOrder.setStatus(status);
        groupOrder.setTotalMoney(order.getTotalMoney());
        groupOrder.setAddtime(TimestampUtils.timestamp());
        groupOrderDao.insertSelective(groupOrder);
        return groupOrder;
    }


    /**
     * 提现接口
     * */
    @Override
    public void entPayment(Double drawAmount, String ip) {
        // 转化为分
        Integer amount = ((Double) (drawAmount * 100)).intValue();
        //查询最后一条记录看看余额
//        DrawCashLogDO drawCashLog = groupServiceDao.getLastCashLog(member.getUid());
//        if (drawCashLog.getTotalMoney() < amount) {
//            // 余额不足
//            throw BusinessException.of(ErrorMessageEnum.BALANCE_NOT_ENOUGH);
//        }

        // 先扣后给原则，先更新数据库
        try {
            //插入成功,申请打款
            EntPayRequest entPayRequest = new EntPayRequest();
            entPayRequest.setPartnerTradeNo("190122071131375");
            entPayRequest.setOpenid("oR3V81baBeAiEjL6juAkYl1GuxvM");
            entPayRequest.setCheckName("NO_CHECK");
            entPayRequest.setAmount(amount);
            entPayRequest.setDescription("仙果提现");
            entPayRequest.setSpbillCreateIp(ip);
            EntPayResult entPayResult = wxPayService.getEntPayService().entPay(entPayRequest);
            // 打款成功，将微信返回的paymentNo填入数据库
            log.info("paymentNo：{}",entPayResult.getPaymentNo());
        } catch (WxPayException e) {
            if(e.getErrCode().equals("NO_AUTH") ){
                throw  BusinessException.of(ErrorMessageEnum.AUTH_NOT_ENOUTH);
            }
            //e.printStackTrace();
            // 提现失败
            throw BusinessException.of(ErrorMessageEnum.OPERATION_FAILURE);
        }


    }

    /**
     * 退款
     * */
    @Override
    public void applyRefund(String orderNo) {
        String orderNum = CodeUtils.createOrderNum();
        // 进行退款
        WxPayRefundRequest refundRequest = WxPayRefundRequest.newBuilder()
            .outTradeNo(orderNo)
            .outRefundNo(orderNum)
            .totalFee(1)
            .refundFee(1)
            .refundFeeType("out_trade_no")
            .refundAccount("REFUND_SOURCE_RECHARGE_FUNDS")
            .build();
        try {
            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);

            //orderService.afterRefund(orderInfo, refundResult, false, isSettlement);

            // 发送模板
//            String reason = "售后退款";
//            String page = "pages/member/myJoinActivity/myJoinActivityDetail/myJoinActivityDetail?order_no="
//                + orderInfo.getOrderNo();
//            String templateId = "YWtc58pSIFs7wolF5xLiyT4YKeUgMzmAy4kF4Z_Hy2s";
//            wxMaService.getMsgService().sendTemplateMsg(
//                WxMaTemplateMessage.builder()
//                    .toUser(orderInfo.getOpenId())
//                    .formId(orderInfo.getPrepayId())
//                    .page(page)
//                    .templateId(templateId)
//                    .data(Lists.newArrayList(
//                        new WxMaTemplateMessage.Data("keyword1", orderInfo.getGroupTitle(), "#173177"),
//                        new WxMaTemplateMessage.Data("keyword2", orderInfo.getTotalPriceYuan() + "元", "#173177"),
//                        new WxMaTemplateMessage.Data("keyword3", orderInfo.getOrderNo(), "#173177"),
//                        new WxMaTemplateMessage.Data("keyword4", reason, "#173177")
//                    ))
//                    .build()
//            );

        }catch (WxPayException e) {
            log.error("退款失败:", e.getMessage());
            throw BusinessException.of(ErrorMessageEnum.REFUND_FAILURE);
        }
    }


    /**
    * 支付订单
    * */
    @Override
    public PayOrderOutputDTO createPayInfo(Integer orderId, String ip) {
        GroupOrderDO groupOrder = groupOrderDao.selectByPrimaryKey(orderId);
        UserDO user = userDao.selectByPrimaryKey(groupOrder.getBuyId());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Instant now = LocalDateTime.now().toInstant(ZoneOffset.of("+8"));
        Instant expire = LocalDateTime.now().plusHours(2L).toInstant(ZoneOffset.of("+8"));
        String baseUrl = wxMpProperties.getBaseUrl();
        String notifyUrl = baseUrl+"/pay/payCallBack";
        WxPayUnifiedOrderRequest orderRequest = WxPayUnifiedOrderRequest.newBuilder()
            .body("蓝月亮洗衣液")
            .outTradeNo(groupOrder.getOrderNo())
            .totalFee(groupOrder.getTotalMoney())
            .openid(user.getOpenid())
            .tradeType("JSAPI")
            .spbillCreateIp(ip)
            .notifyUrl(notifyUrl)
            .timeStart(dateFormat.format(Date.from(now)))
            .timeExpire(dateFormat.format(Date.from(expire)))
            .build();
        WxPayUnifiedOrderResult orderResult;
        try {
            orderResult = wxPayService.unifiedOrder(orderRequest);
            log.info("orderResult{}",orderRequest);
        } catch (WxPayException e) {
            log.info("e{}",e.getReturnMsg());
            if(e.getErrCode().equals("ORDERPAID")){
                throw BusinessException.of(ErrorMessageEnum.ORDER_IS_PAYED);
            }else{
                throw BusinessException.of(ErrorMessageEnum.ORDER_PAY_ERROR);
            }
        }
        WxPayConfig payConfig = wxPayService.getConfig();
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
        String nonceStr = String.valueOf(System.currentTimeMillis());
        String signType = "MD5";

        Map<String, String> payInfo = new HashMap<>();
        payInfo.put("appId", payConfig.getAppId());
        payInfo.put("timeStamp", timestamp);
        payInfo.put("nonceStr", nonceStr);
        payInfo.put("package", "prepay_id=" + orderResult.getPrepayId());
        payInfo.put("signType", "MD5");
        String sign = SignUtils.createSign(
            payInfo, signType, payConfig.getMchKey(), false
        );
        // 构建结果
        PayOrderOutputDTO output = new PayOrderOutputDTO();
        output.setAppid(payConfig.getAppId());
        output.setMchId(payConfig.getMchId());
        output.setPrepayId(orderResult.getPrepayId());
        output.setNonceStr(nonceStr);
        output.setResultCode("SUCCESS");
        output.setNotifyUrl(notifyUrl);
        output.setSign(sign);
        output.setTimeStamp(timestamp);
        return output;

        //end

    }


    /**
     * 测试发红包
     * */
    @Override
    public void sendRedPacket(String ip) {
        //new

        WxPaySendRedpackRequest req = new WxPaySendRedpackRequest();
        req.setMchBillNo("19010818081358"); // 商户订单号
        req.setReOpenid("oR3V81QxrDYq9mCgidJLH23ke30w"); // 用户的openid
        req.setSendName("仙果科技"); // 红包发送者名称
        req.setTotalAmount(100);// 付款金额 限制 大于100 小于200*100，单位分
        req.setTotalNum(1); // 红包发放人数
        req.setWishing("新春祝福"); // 包祝福语
        req.setActName("新春拜年"); // 活动名称
        req.setRemark("新春祝福"); // 备注
        req.setClientIp(ip); // 请求的客户端Ip地址

        try {
            WxPaySendRedpackResult result = wxPayService.sendRedpack(req);
            if(result.getResultCode().equals("SUCCESS")){
              //todo
            }else{
                //回写DB
                if(result.getErrCode().equals("NOTENOUGH")){
                    throw BusinessException.of(ErrorMessageEnum.MONEY_NOTENOUGH);
                }
                log.info("retyen_code:{}",result.getErrCode());
                log.info("mag:{}",result.getErrCodeDes());
            }
            //log.info(ReflectionToStringBuilder.toString(result));
        } catch (WxPayException e) {
            //e.printStackTrace();
            String message = e.getMessage();
            log.info("==pay====>>>发送失败：" + message);
        }
    }


}
